package com.geek.conc;

import lombok.SneakyThrows;

import java.util.concurrent.*;

/**
 * @program geek_conc
 * @description: 思考有多少种方式，在 main 函数启动一个新线程，运行一个方法，拿到这个方法的返回值后，退出主线程?
 * @author: chanzhugang
 * @create: 2021/04/10 23:36
 */
public class Homework03 {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        doMethod1();

        doMethod2();

        doMethod3();

        doMethod4();

        long end = System.currentTimeMillis();
        System.out.println("使用时间为:" + (end - start) + "ms");
    }


    @SneakyThrows
    private static void doMethod1() {
        Thread thread = new Thread(() -> {
            int result = sum();
            System.out.println("异步执行结果为：" + result);
        });
        thread.start();
        // 子线程执行完
        thread.join();
    }

    @SneakyThrows
    private static void doMethod2() {
        FutureTask<Integer> task = new FutureTask<>(() -> sum());
        new Thread(task).start();
        Integer result = task.get();
        System.out.println("异步执行结果为：" +result);
    }

    @SneakyThrows
    private static void doMethod3() {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        executorService.submit(() -> {
            try {
                int result = sum();
                System.out.println("异步执行结果为：" + result);
            } finally {
                countDownLatch.countDown();
            }
        });
        countDownLatch.await();
        executorService.shutdown();
    }


    private static void doMethod4() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            int result = sum();
            System.out.println("异步执行结果为：" + result);

        });

        CompletableFuture.allOf(future).join();
    }


    private static int sum() {
        return fibo(36);
    }

    /**
     * 斐波那契
     */
    private static int fibo(int a) {
        if (a < 2) {
            return 1;
        }
        return fibo(a - 1) + fibo(a - 2);
    }
}